#include <bits/stdc++.h>

#define pb push_back
#define ep emplace
#define eb emplace_back
#define fi first
#define se second
#define in read()
#define rep(i, x, y) for(int i = (x); i <= (y); i++)
#define per(i, x, y) for(int i = (x); i >= (y); i--)

using namespace std;

using ll = long long;
using db = double;
using pii = pair < int, int >;
using vec = vector < int >;
using veg = vector < pii >;

int read() {
	int x = 0; bool f = 0; char ch = getchar();
	while(!isdigit(ch)) f |= ch == '-', ch = getchar();
	while(isdigit(ch)) x = x * 10 + (ch ^ 48), ch = getchar();
	return f ? -x : x;
}

const int N = 6e5 + 10;
const db alpha = 2.0;

int tot;

struct node {
	int ch[26], v, f;
} a[N], b[N];

int cnt;
char s[N];

struct ACAM {
	vec pot; int rt;
	void init(char *s, int op) {
		vec().swap(pot); pot.eb(rt = ++tot); int ls = strlen(s + 1), p = rt;
		rep(i, 1, ls) {
			int x = s[i] - 'a';
			if(!b[p].ch[x]) pot.eb(b[p].ch[x] = ++tot);
			p = b[p].ch[x];
		} b[p].v = op;
	}
	void build() {
		for(auto v : pot) a[v] = b[v];
		rep(i, 0, 25) a[0].ch[i] = rt;
		queue < int > q; q.ep(rt);
		while(!q.empty()) {
			int x = q.front(), F = a[x].f; q.pop();
			rep(i, 0, 25) {
				if(!a[x].ch[i]) a[x].ch[i] = a[F].ch[i];
				else a[a[x].ch[i]].f = a[F].ch[i], q.ep(a[x].ch[i]);
			} a[x].v += a[a[x].f].v;
		}
	}
	int query(char *t) {
		int lt = strlen(t + 1), p = rt, tot = 0;
		rep(i, 1, lt) {
			int x = t[i] - 'a';
			p = a[p].ch[x]; tot += a[p].v;
		} return tot;
	}
	void merge(int x, int y) {
		if(x == y) pot.eb(x);
		else b[x].v += b[y].v;
		rep(i, 0, 25)
			if(b[y].ch[i]) {
				if(!b[x].ch[i]) b[x].ch[i] = b[y].ch[i];
				merge(b[x].ch[i], b[y].ch[i]);
			}
	}
} S[50];

int main() {
#ifndef ONLINE_JUDGE
	freopen("1.in", "r", stdin);
#endif
	int m = in;
	while(m--) {
		int op = in; scanf("%s", s + 1);
		if(op == 3) {
			int ans = 0; rep(i, 1, cnt) ans += S[i].query(s);
			printf("%d\n", ans); fflush(stdout);
		} else {
			S[++cnt].init(s, op == 1 ? 1 : -1);
			while(cnt > 1 && S[cnt].pot.size() * alpha > S[cnt - 1].pot.size()) S[cnt - 1].merge(S[cnt - 1].rt, S[cnt].rt), cnt--;
			S[cnt].build();
		}
	}
	return 0;
}
